/*
 * @Author: soso
 * @Date: 2022-02-08 17:18:19
 * @LastEditTime: 2022-02-11 13:58:07
 * @LastEditors: Please set LastEditors
 * @Description: 磁盘变动的本地存储
 * @FilePath: /sync-client/notify/nf.go
 */

package notify

import (
	"gomeshcli/sconfig"
	"sync"
	"time"
)

type Ntfs struct {
	queueNtfs   []*sconfig.Snotify // 实时有限长度队列
	fullNtfs    []*sconfig.Snotify // 所有现存待处理命令
	runningNtfs []*sconfig.Snotify // 处理中的命令
	keepLen     int
}

var (
	ntfsSingleton *Ntfs
	onceNtfs      sync.Once
)

func NewNtfs() *Ntfs {
	onceNtfs.Do(func() {
		ntfsSingleton = &Ntfs{
			keepLen:     50,
			queueNtfs:   []*sconfig.Snotify{},
			fullNtfs:    []*sconfig.Snotify{},
			runningNtfs: []*sconfig.Snotify{},
		}
		// ntfsSingleton.loadRunningFile()
		// ntfsSingleton.loadFullNtfs()
	})

	return ntfsSingleton
}

// 增加系统监测命令
func (nf *Ntfs) Add(ntf sconfig.Snotify) {
	// 保持限制长度
	nf.queueNtfs = append(nf.queueNtfs, &ntf)
	if len(nf.queueNtfs) > nf.keepLen {
		nf.queueNtfs = nf.queueNtfs[len(nf.queueNtfs)-nf.keepLen:]
	}

	// 过滤重复命令(一般为磁盘Write会生成多次Write命令)
	lastNtf, same := nf.isSameWithLastAct(ntf)

	if same {
		lastNtf.Ctime = time.Now()
		return
	} else {
		nf.fullNtfs = append(nf.fullNtfs, &ntf) // 保存到全部命令记录中
		// nf.appendFullFile(ntf)
	}
}

// 读取实时命令序列
func (nf *Ntfs) GetNtfs() []*sconfig.Snotify {
	return nf.queueNtfs
}

// 读取监测命令列表
func (nf *Ntfs) GetFullNtfs() []*sconfig.Snotify {
	return nf.fullNtfs
}

// 是否与上次系统发出的命令相同
// (常见于Write命令，系统会频繁发出Write命令)
func (nf *Ntfs) isSameWithLastAct(curNtf sconfig.Snotify) (lastNtf *sconfig.Snotify, same bool) {
	if len(nf.queueNtfs) <= 1 {
		return nil, false
	}
	lastNtf = nf.queueNtfs[len(nf.queueNtfs)-2]
	return lastNtf, lastNtf.Act == curNtf.Act && lastNtf.Path == curNtf.Path
}

// 将全部命令移动到待处理命令列表中
func (nf *Ntfs) MoveFullToRunning() error {
	nf.runningNtfs = nf.fullNtfs
	nf.fullNtfs = []*sconfig.Snotify{}
	nf.queueNtfs = []*sconfig.Snotify{}

	return nil
	// if err := os.Rename(pathOfFull, pathOfRunning); err == nil {
	// } else {
	// 	return err
	// }
}

// 删除待处理命令列表
func (nf *Ntfs) removeRunnings(deletedMap map[string]bool) {
	lenrunning := len(nf.runningNtfs)
	for i := lenrunning - 1; i >= 0; i-- {
		if _, ok := deletedMap[nf.runningNtfs[i].Path]; ok {
			nf.runningNtfs = append(nf.runningNtfs[:i], nf.runningNtfs[i+1:]...)
		}
	}
}
